package com.zp.business.impl.clinicOrder;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zp.base.api.RemoteClinicItemDictService;
import com.zp.base.api.RemoteSerialNumberUtils;
import com.zp.base.api.vo.ClinicItemDictVo;
import com.zp.base.api.vo.PerformFreqDictVo;
import com.zp.business.entity.clinicOrder.ClinicOrders;
import com.zp.business.entity.clinicOrder.ClinicOrdersCost;
import com.zp.business.entity.clinicOrder.OutpTreatRec;
import com.zp.business.entity.clinicOrder.bo.ApplyItemBo;
import com.zp.business.entity.clinicOrder.bo.ClinicOrderParam;
import com.zp.business.entity.clinicOrder.bo.OutpTreatRecBo;
import com.zp.business.entity.clinicOrder.vo.OutpTreatRecVo;
import com.zp.business.mapper.clinicOrder.ClinicOrdersCostMapper;
import com.zp.business.mapper.clinicOrder.OutpTreatRecMapper;
import com.zp.business.service.clinicOrder.IClinicOrdersService;
import com.zp.business.service.clinicOrder.IOutpTreatRecService;
import com.zp.business.service.patient.IClinicMasterService;
import com.zp.common.core.constant.BaseConstants;
import com.zp.common.core.constant.CacheNames;
import com.zp.common.core.constant.UserConstants;
import com.zp.common.core.utils.StringUtils;
import com.zp.common.myBatis.core.page.PageQuery;
import com.zp.common.myBatis.core.page.TableDataInfo;
import com.zp.common.redis.utils.CacheUtils;
import com.zp.system.api.entity.SysDept;
import com.zp.system.api.entity.SysUser;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.RequiredArgsConstructor;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 处置治疗Service业务层处理
 *
 * @author zhang peng
 * @ date 2024-01-05
 */
@RequiredArgsConstructor
@Service
public class OutpTreatRecServiceImpl implements IOutpTreatRecService {

    private final OutpTreatRecMapper baseMapper;

    private final IClinicOrdersService clinicOrdersService;
    private final IClinicMasterService clinicMasterService;
    private final ClinicOrdersCostMapper clinicOrdersCostMapper;
    @DubboReference
    private RemoteClinicItemDictService clinicItemDictService;
    @DubboReference
    private RemoteSerialNumberUtils remoteSerialNumberUtils;

    static Map<String, PerformFreqDictVo> performFreqDictMap = CacheUtils.get(CacheNames.PERFORM_FREQ_DICT);


    /**
     * 用户信息
     */
    static Map<String, SysUser> sysUserMap = CacheUtils.get(CacheNames.SYS_USER);

    static Map<String, SysDept> sysDeptMap = CacheUtils.get(CacheNames.SYS_DEPT);

    /**
     * 查询处置治疗
     */
    @Override
    public OutpTreatRecVo queryById(String id) {
        return baseMapper.selectVoById(id);
    }

    /**
     * 查询处置治疗列表(分页)
     */
    @Override
    public TableDataInfo<OutpTreatRecVo> queryPageList(OutpTreatRecBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<OutpTreatRec> lqw = buildQueryWrapper(bo);
        Page<OutpTreatRecVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        result.getRecords().forEach(item -> {
            item.setApplyDeptName(CollectionUtil.isNotEmpty(sysDeptMap) && StringUtils.isNotEmpty(item.getApplyDept())
                    ? sysDeptMap.get(item.getApplyDept()).getDeptName() : "");
            item.setImplementDeptName(CollectionUtil.isNotEmpty(sysDeptMap) && StringUtils.isNotEmpty(item.getImplementDept())
                    ? sysDeptMap.get(item.getImplementDept()).getDeptName() : "");
            item.setPerformFreqName(CollectionUtil.isNotEmpty(performFreqDictMap) && StringUtils.isNotEmpty(item.getPerformFreq())
                    ? performFreqDictMap.get(item.getPerformFreq()).getFreqDesc() : "");
        });
        return TableDataInfo.build(result);
    }

    /**
     * 查询处置治疗列表(不分页)
     */
    @Override
    public List<OutpTreatRecVo> queryList(OutpTreatRecBo bo) {
        LambdaQueryWrapper<OutpTreatRec> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<OutpTreatRec> buildQueryWrapper(OutpTreatRecBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<OutpTreatRec> lqw = Wrappers.lambdaQuery();
        lqw.eq(StringUtils.isNotBlank(bo.getClinicId()), OutpTreatRec::getClinicId, bo.getClinicId());
        lqw.eq(StringUtils.isNotBlank(bo.getClinicOrdersId()), OutpTreatRec::getClinicOrdersId, bo.getClinicOrdersId());
        lqw.eq(StringUtils.isNotBlank(bo.getPatientId()), OutpTreatRec::getPatientId, bo.getPatientId());
        lqw.eq(StringUtils.isNotBlank(bo.getInoroutFlag()), OutpTreatRec::getInoroutFlag, bo.getInoroutFlag());
        lqw.eq(StringUtils.isNotBlank(bo.getConfirmFlag()), OutpTreatRec::getConfirmFlag, bo.getConfirmFlag());
        lqw.eq(StringUtils.isNotBlank(bo.getChargeFlag()), OutpTreatRec::getChargeFlag, bo.getChargeFlag());
        lqw.eq(StringUtils.isNotBlank(bo.getStockId()), OutpTreatRec::getStockId, bo.getStockId());
        lqw.eq(StringUtils.isNotBlank(bo.getGroupNo()), OutpTreatRec::getGroupNo, bo.getGroupNo());
        lqw.like(StringUtils.isNotBlank(bo.getApplyNo()), OutpTreatRec::getApplyNo, bo.getApplyNo());
        lqw.eq(StringUtils.isNotBlank(bo.getImplementDept()), OutpTreatRec::getImplementDept, bo.getImplementDept());
        lqw.eq(StringUtils.isNotBlank(bo.getApplyDept()), OutpTreatRec::getApplyDept, bo.getApplyDept());
        lqw.eq(StringUtils.isNotBlank(bo.getPerformFreq()), OutpTreatRec::getPerformFreq, bo.getPerformFreq());
        lqw.like(StringUtils.isNotBlank(bo.getItemName()), OutpTreatRec::getItemName, bo.getItemName());
        lqw.eq(bo.getNum() != null, OutpTreatRec::getNum, bo.getNum());
        lqw.eq(bo.getSumPrice() != null, OutpTreatRec::getSumPrice, bo.getSumPrice());
        lqw.eq(StringUtils.isNotBlank(bo.getOrgId()), OutpTreatRec::getOrgId, bo.getOrgId());
        lqw.eq(StringUtils.isNotBlank(bo.getRemarks()), OutpTreatRec::getRemarks, bo.getRemarks());
        lqw.eq(StringUtils.isNotBlank(bo.getIsApply()), OutpTreatRec::getIsApply, bo.getIsApply());
        lqw.eq(StringUtils.isNotBlank(bo.getIsPhy()), OutpTreatRec::getIsPhy, bo.getIsPhy());
        lqw.eq(StringUtils.isNotBlank(bo.getClinicItemId()), OutpTreatRec::getClinicItemId, bo.getClinicItemId());
        lqw.eq(StringUtils.isNotBlank(bo.getItemClass()), OutpTreatRec::getItemClass, bo.getItemClass());
        lqw.eq(StringUtils.isNotBlank(bo.getUnitsStr()), OutpTreatRec::getUnitsStr, bo.getUnitsStr());
        lqw.like(StringUtils.isNotBlank(bo.getSupplierName()), OutpTreatRec::getSupplierName, bo.getSupplierName());
        lqw.eq(StringUtils.isNotBlank(bo.getPackageSpec()), OutpTreatRec::getPackageSpec, bo.getPackageSpec());
        lqw.eq(bo.getCoefficient() != null, OutpTreatRec::getCoefficient, bo.getCoefficient());
        lqw.eq(bo.getPrice() != null, OutpTreatRec::getPrice, bo.getPrice());
        lqw.eq(bo.getTradePrice() != null, OutpTreatRec::getTradePrice, bo.getTradePrice());
        lqw.eq(bo.getNetworkPrice() != null, OutpTreatRec::getNetworkPrice, bo.getNetworkPrice());
        lqw.eq(StringUtils.isNotBlank(bo.getIsClinicFee()), OutpTreatRec::getIsClinicFee, bo.getIsClinicFee());
        lqw.eq(StringUtils.isNotBlank(bo.getMark()), OutpTreatRec::getMark, bo.getMark());
        lqw.eq(bo.getAbidance() != null, OutpTreatRec::getAbidance, bo.getAbidance());
        lqw.orderByDesc(OutpTreatRec::getCreateTime);
        return lqw;
    }

    /**
     * 新增处置治疗
     */
    @Override
    @GlobalTransactional
    public Boolean insertByBo(OutpTreatRecBo bo) {
        // 组织门诊医嘱参数信息
        ClinicOrderParam clinicOrderParam = initClinicOrderParam(bo);
        if (StringUtils.isEmpty(clinicOrderParam.getApplyNo())) {
            clinicOrderParam.setApplyNo(remoteSerialNumberUtils.generateOutpTreatNo(bo.getOrgId()));
        } else {
            clinicOrderParam.setApplyNo(clinicOrderParam.getApplyNo());
        }
        OutpTreatRec add = BeanUtil.toBean(bo, OutpTreatRec.class);
        validEntityBeforeSave(add);
        add.initEntity();
        boolean flag = true;
        List<ApplyItemBo> applyItemBoList = new ArrayList<>();
        ApplyItemBo applyItemBo = new ApplyItemBo();
        applyItemBo.setApplyItemId(bo.getId());
        applyItemBo.setClinicItemId(bo.getClinicItemId());
        applyItemBo.setNum(bo.getNum());
        applyItemBoList.add(applyItemBo);
        clinicOrderParam.setApplyItemBoList(applyItemBoList);
        clinicOrderParam.setNum(1);
        List<OutpTreatRec> outpTreatRecs = saveByBo(clinicOrderParam);
        // 保存clinicOrder、clinicOrderCost信息
        ClinicOrders clinicOrders = clinicOrdersService.initClinicOrders(clinicOrderParam);
        bo.setClinicOrdersId(clinicOrders.getId());
        clinicOrderParam.setClinicOrdersId(clinicOrders.getId());
        baseMapper.update(null, new LambdaUpdateWrapper<OutpTreatRec>()
                .set(OutpTreatRec::getClinicOrdersId, clinicOrders.getId())
                .eq(OutpTreatRec::getId, outpTreatRecs.get(0).getId())
        );
        bo.setId(add.getId());
        clinicMasterService.updateDoctorId(bo.getClinicId(), bo.getIsUpdateDoctorId());
        return flag;
    }


    public ClinicOrderParam initClinicOrderParam(OutpTreatRecBo bo) {
        ClinicOrderParam clinicOrderParam = BeanUtil.toBean(bo, ClinicOrderParam.class);
        List<String> clinicItemIds = new ArrayList<>();
        clinicItemIds.add(bo.getClinicItemId());
        clinicOrderParam.setItemClinicIds(clinicItemIds);
        return clinicOrderParam;
    }

    /**
     * 修改处置治疗
     */
    @Override
    public Boolean updateByBo(OutpTreatRecBo bo) {
        OutpTreatRec update = BeanUtil.toBean(bo, OutpTreatRec.class);
        update.updateInfo();
        validEntityBeforeSave(update);
        boolean b = baseMapper.updateById(update) > 0;
        if (b) {
            clinicMasterService.updateDoctorId(bo.getClinicId(), bo.getIsUpdateDoctorId());
        }
        return b;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(OutpTreatRec entity) {
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 批量删除处置治疗
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<String> ids, Boolean isValid) {
        if (isValid) {
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteBatchIds(ids) > 0;
    }

    /**
     * 门诊处置治疗项目保存
     *
     * @param param
     * @return
     */
    @Override
    @Transactional
    public List<OutpTreatRec> saveByBo(ClinicOrderParam param) {
        List<OutpTreatRec> outpTreatRecSaveList = initOutpTreatRec(param);
        baseMapper.insertBatch(outpTreatRecSaveList);
        return outpTreatRecSaveList;
    }

    /**
     * 组织OutpTreatRec数据（检查）
     *
     * @param param
     * @return
     */
    public List<OutpTreatRec> initOutpTreatRec(ClinicOrderParam param) {
        List<OutpTreatRec> outpTreatRecSaveList = new ArrayList<>();
        param.getApplyItemBoList().forEach(applyItemBo -> {
            OutpTreatRec outpTreatRec = new OutpTreatRec();
            outpTreatRec.initEntity();
//            outpTreatRec.setId(String.valueOf(SnowIdUtils.uniqueString()));
            outpTreatRec.setApplyNo(param.getApplyNo());
            outpTreatRec.setClinicId(param.getClinicId());
            outpTreatRec.setPatientId(param.getPatientId());
            outpTreatRec.setGroupNo(param.getGroupNo());
            outpTreatRec.setClinicOrdersId(param.getClinicOrdersId());
            outpTreatRec.setChargeFlag(BaseConstants.CHARGE_FLAG_DICT.ONE);
            outpTreatRec.setInoroutFlag(param.getInoroutFlag());
            // 设置确认类型： 未确认 1
            outpTreatRec.setConfirmFlag(BaseConstants.CONFIRM_FLAG.UNISSUED);
            outpTreatRec.setImplementDept(param.getImplementDept());
            outpTreatRec.setApplyDept(param.getApplyDept());
            outpTreatRec.setApplyUser(param.getApplyUser());
            outpTreatRec.setOrgId(param.getOrgId());
            outpTreatRec.setIsApply(param.getIsApply());
            outpTreatRec.setIsPhy(UserConstants.NO);
            outpTreatRec.setNum(applyItemBo.getNum());
            outpTreatRec.setAbidance(param.getAbidance());
            outpTreatRec.setPerformFreq(param.getPerformFreq());
            outpTreatRec.setRemarks(param.getRemarks());
            outpTreatRec.setApplyItemId(applyItemBo.getApplyItemId());
            tissueClinicItemPrice(outpTreatRec, applyItemBo.getClinicItemId());
            outpTreatRecSaveList.add(outpTreatRec);
        });
        return outpTreatRecSaveList;
    }

    public void tissueClinicItemPrice(OutpTreatRec outpTreatRec, String clinicItemId) {
        List<ClinicItemDictVo> clinicItemDictList = clinicItemDictService.getClinicItemDictList(clinicItemId);
        if (CollectionUtil.isNotEmpty(clinicItemDictList)) {
            ClinicItemDictVo clinicItemDictVo = clinicItemDictList.get(0);
            outpTreatRec.setClinicItemId(clinicItemDictVo.getClinicItemId());
            outpTreatRec.setItemName(clinicItemDictVo.getItemName());
            outpTreatRec.setItemCode(clinicItemDictVo.getItemCode());
            // 单价
            outpTreatRec.setPrice(BigDecimal.valueOf(clinicItemDictVo.getSubTotal()));
            BigDecimal subTotal = BigDecimal.valueOf(clinicItemDictVo.getSubTotal() * outpTreatRec.getNum());
            outpTreatRec.setSumPrice(subTotal);
            outpTreatRec.setTradePrice(subTotal);
            outpTreatRec.setIsClinicFee(UserConstants.NO);
            outpTreatRec.setMark(UserConstants.YES);
            outpTreatRec.setItemClass(clinicItemDictVo.getItemClass());
        }
    }

    @Override
    @Transactional
    public Boolean deleteByBo(String orgId, String applyNo) {
        Map<String, Object> columnMap = new HashMap<String, Object>();
        columnMap.put("org_id", orgId);
        columnMap.put("apply_no", applyNo);
        return baseMapper.deleteByMap(columnMap) > 0;
    }

    /**
     * @ Author zhangpeng
     * @ Description 遍历删除项目
     * @ Date 17:04 2024/3/21
     * @ Param ids OutpTreatRec id集合
     * @ return
     **/
    @Override
    @Transactional
    public Boolean ergodicDeleteBo(List<String> ids) {
        List<OutpTreatRecVo> outpTreatRecVos = baseMapper.selectVoBatchIds(ids);
        baseMapper.deleteBatchIds(ids);
        List<String> orderIds = outpTreatRecVos.stream().map(OutpTreatRecVo::getClinicOrdersId).collect(Collectors.toList());
        clinicOrdersService.deleteWithValidByIds(orderIds, false);
        return clinicOrdersCostMapper.delete(Wrappers.<ClinicOrdersCost>lambdaQuery()
                .in(ClinicOrdersCost::getOrdersId, orderIds)
        ) > 0;
    }

    @Override
    @Transactional
    public boolean update(LambdaUpdateWrapper<OutpTreatRec> outpTreatRecLambdaUpdateWrapper) {
        return baseMapper.update(outpTreatRecLambdaUpdateWrapper) > 0;
    }
}
